<?php

namespace frontend\modules\trade\models;

use Yii;
use yii\db\Exception;
use yii\helpers\VarDumper;
use common\models\trade\UnifiedPayment as Trade;
use common\models\trade\TradeOrder;
use common\models\trade\HandleTrade;
use common\helpers\Utils;
use common\helpers\ArrayHelper;

/**
 * 创建支付订单
 * TradeOrderForm use to create trade payment order model.
 * 
 * @author emhome <emhome@163.com>
 * @since 1.0
 */
class TradeOrderForm extends BizOrderModel {

    /**
     * @var integer 支付超时时间
     */
    const PAYMENT_EXPIRED_DURATION = 1800;

    /**
     * @var string(16) 交易使用的支付方式 alipay|wechat
     */
    public $paymode;

    /**
     * @var integer 类型ID
     */
    public $partner_id = 2;

    /**
     * 交易中心统一下单请求参数校验
     * @inheritdoc
     */
    public function rules() {
        return ArrayHelper::merge(parent::rules(), [
            [['paymode'], 'required'],
            ['paymode', 'in', 'range' => ['alipay', 'wechat']],
            ['partner_id', 'safe'],
        ]);
    }

    /**
     * Sends an email to the specified email address using the information collected by this model.
     *
     * @param string $email the target email address
     * @return bool whether the email was sent
     */
    public function save() {
        if (!$this->validate()) {
            return $this->dumpError('统一支付下单失败');
        }

        $model = $this->getModel();
        $bizno = $model->order_no;
        $total = $model->price;

        //取消当前外部订单号下的所有历史交易
        if (HandleTrade::cancelByBizno($bizno, $msg) === false) {
            return $this->dumpError('待支付交易创建时处理失败');
        }

        $expiretime = time() + self::PAYMENT_EXPIRED_DURATION;

        //创建交易
        $trade = new Trade();
        Yii::error($trade->attributes, __METHOD__);
        $tradeNo = $trade->generateTn($this->paymode, $this->partner_id);
        $tradeAttributes = [
            'user_id' => $this->user_id,
            'credit' => 0,
            'paymode' => $this->paymode,
            'bizno' => $bizno,
            'unified_no' => $bizno,
            'total' => $total,
            'cash' => $total,
            'credit' => 0,
            'partner_id' => $this->partner_id,
            'subject' => $model->title,
            'body' => $model->descirption,
            'expire_time' => $expiretime,
            'balance' => Trade::BALANCE_PAYMENT,
            'status' => Trade::STATUS_WAITPAY,
        ];
        Yii::error($tradeAttributes, __METHOD__);
        $trade->setAttributes($tradeAttributes);

        //创建现金交易
        $cashOrder = new TradeOrder();
        $cashOrder->attributes = [
            'paymode' => $this->paymode,
            'currency' => TradeOrder::CURRENCY_CNY,
            'balance' => TradeOrder::BALANCE_PAYMENT,
            'original_no' => $tradeNo,
            'expire_time' => $expiretime,
            'status' => TradeOrder::STATUS_DEFAULT,
        ];
        $cashOrder->setPayType($this->paymode, $this->partner_id);
        //开启事务
        $transaction = Yii::$app->db->beginTransaction();
        try {
            if (!$trade->save()) {
                throw new Exception('交易创建失败！' . Utils::arrayToString($trade->errors, true));
            }
            $cashOrder->pay = $total;
            $cashOrder->trade_id = $trade->id;
            if (!$cashOrder->save()) {
                throw new Exception('现金交易创建失败！' . Utils::arrayToString($cashOrder->errors, true));
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $msg = $e->getMessage();
            Yii::error($msg . "\n" . VarDumper::export($this->attributes), 'payment');
            return false;
        }

        Yii::error([
            'attributes' => $this->attributes,
            'trade' => $trade->attributes,
            'cashOrder' => $cashOrder->attributes,
        ], __METHOD__);

        //创建自动过期任务队列
//        $taskid = Yii::$app->queue->delay($this->expire_time - time())->push(new \common\jobs\TradeExpiredJob([
//            'tradeid' => $trade->id
//        ]));
//        Yii::$app->commonCache->set('queue_trade_' . $trade->id, $taskid);

        return $trade;
    }

}
